extends Node


## 控制器映射
## 如： [{"device": "key_", "charactor_id": -1, "peer_id": 1}, {"device": "joy0_", "charactor_id": -1, "peer_id": 2}]
var controller_data: Array = []

var player_peer_ids := []
var current_player: Player

const SERVER_PORT := 7790 #房主服务器端口
var peer: ENetMultiplayerPeer


@onready var main: Main = get_node("/root/Main") if has_node("/root/Main") else null #主场景
@onready var multiplayer_spawn: MultiplayerSpawn = get_node("/root/Main/Keep/MultiplayerSpawn")  if has_node("/root/Main/Keep/MultiplayerSpawn") else null #玩家出生管理
@onready var ui: Ui = get_node("/root/Main/Keep/Ui")  if has_node("/root/Main/Keep/Ui") else null #UI
@onready var main_camera: MultiplayerCamera = get_node("/root/Main/Keep/MultiplayerCamera")  if has_node("/root/Main/Keep/MultiplayerCamera") else null # 相机

var current_level := -1:
	set(v):
		SignalManager.level_update.emit(v)
		current_level = v


var level_map: Array = [
	preload("res://entity/level/level1.tscn"),
	preload("res://entity/level/level2.tscn"),
]

var hall_tscn := preload("res://entity/layout/hall.tscn")


enum  GameType {
	SINGLE, ## 单人游戏
	MULTI_SAME_SCREEN, ## 多人同屏
	WLAN, ## 局域网联机
}
## 游戏模式
var current_type: GameType = GameType.SINGLE


#游戏状态
var current_state := GameState.ZERO
enum GameState {
	ZERO,
	HALL, #大厅
	ROOM, #房间选择
	GAMING, #游戏中
	GAMING_MENU, #游戏中-调出菜单
	GAMING_MENU_SETTING, #游戏中-调出菜单-设置
	PAUSE,  #游戏暂停
	GAME_OVER, #游戏结束
}

###################################################################################################
var room_status: Dictionary = {"normal": "未开始", "gaming": "正在游戏"}
var room_info := {"name": "", "count": 0, "ip": "", "player_id": [], "status": "normal", "level": 1} #房间信息

const LISTEN_PORT := 7788 #监听广播端口
const BROADCAST_PORT := 7787 #发送广播端口

signal found_server(ip, port, room_info)
signal removed_server(ip)

var broadcaster : PacketPeerUDP
var listener : PacketPeerUDP

###################################################################################################

func setup_listener() -> void:
	listener = PacketPeerUDP.new()
	var ok := listener.bind(LISTEN_PORT)
	if ok == OK:
		Debug.log_str(["listener port success", LISTEN_PORT])
	else:
		Debug.log_str(["listener port fail", LISTEN_PORT])


func setup_broadcast(room_name: String) -> void:
	var local_ip := NetHelper.get_local_ip()
	var prev_ip: String = room_info.ip
	
	room_info.ip = local_ip
	room_info.name = room_name
	room_info.count = player_peer_ids.size()
	
	if prev_ip == "":
		var broadcast_ip := NetHelper.get_broadcast_ip()
		broadcaster = PacketPeerUDP.new()
		broadcaster.set_broadcast_enabled(true)
		broadcaster.set_dest_address(broadcast_ip, LISTEN_PORT)
		var ok := broadcaster.bind(BROADCAST_PORT)
		if ok == OK:
			Debug.log_str(["broadcast port success", local_ip, BROADCAST_PORT])
		else:
			Debug.log_str(["broadcast port fail", local_ip, BROADCAST_PORT])
		
		found_server.emit(local_ip, LISTEN_PORT, room_info)
		create_server()
	push_packet()


func push_packet() -> void:
	if broadcaster:
		room_info.count = player_peer_ids.size()
		var data := JSON.stringify(room_info)
		var packet := data.to_utf8_buffer()
		broadcaster.put_packet(packet)


func clean_server() -> void:
	listener.close()
	
	if broadcaster:
		broadcaster.close()
		removed_server.emit(NetHelper.get_local_ip())

###################################################################################################


func _ready() -> void:
	multiplayer.peer_connected.connect(_on_peer_connected)
	multiplayer.peer_disconnected.connect(_on_peer_disconnected)
	multiplayer.connected_to_server.connect(_on_connected_to_server)
	multiplayer.connection_failed.connect(_on_connection_failed)
	multiplayer.server_disconnected.connect(_on_server_disconnected)


# 仅客户端
func _on_connected_to_server() -> void:
	send_player_info.rpc_id(1, multiplayer.get_unique_id())
	push_packet()


# 仅客户端
func _on_connection_failed() -> void:
	Debug.log_str(["_on_connection_failed"])


# 仅客户端
func _on_server_disconnected() -> void:
	for p: Player in get_tree().get_nodes_in_group("player"):
		player_peer_ids.erase(p.name.to_int())
		p.queue_free()
	set_state(GameState.GAME_OVER)


# 客户端 + 服务端,当客户端断开连接
func _on_peer_disconnected(id: int) -> void:
	Debug.log_str(["_on_peer_disconnected"])
	remove_player(id)
	remove_player.rpc(id)



# 客户端 + 服务端,当有新的客户端连接时，该方法会被触发
func _on_peer_connected(id: int) -> void:
	printt("_on_peer_connected peer_id:", id)


## 创建服务器
func create_server() -> void:
	#创建服务器
	peer = ENetMultiplayerPeer.new()
	var error = peer.create_server(SERVER_PORT)
	if error != OK:
		printerr("创建服务器失败，错误码：", error, " 端口：", SERVER_PORT)
		return
	
	peer.get_host().compress(ENetConnection.COMPRESS_RANGE_CODER)
	#最为服务器，需要监听是否有别的客户端进行连接
	multiplayer.multiplayer_peer = peer
	send_player_info(multiplayer.get_unique_id())


## 加入游戏
func join_server(ip: String) -> void:
	# 创建客户端，连接服务器
	if peer:
		var uni_id := multiplayer.get_unique_id()
		multiplayer.multiplayer_peer = null
		if uni_id:
			remove_player(uni_id)
			remove_player.rpc(uni_id)
		peer.close()
	peer = ENetMultiplayerPeer.new()
	var error := peer.create_client(ip, SERVER_PORT)
	if error != OK: return
	peer.get_host().compress(ENetConnection.COMPRESS_RANGE_CODER)
	multiplayer.multiplayer_peer = peer


## 获取当前控制权玩家
func get_current_player() -> Player:
	if not current_player or not is_instance_valid(current_player):
		var players := get_tree().get_nodes_in_group("player");
		for p: Player in players:
			if p.peer_id == multiplayer.get_unique_id():
				current_player = p
				break
	return current_player


## 保存玩家id
@rpc("any_peer")
func send_player_info(id: int) -> void:
	if not id in player_peer_ids:
		player_peer_ids.append(id)
	
	if multiplayer.is_server():
		for i in player_peer_ids:
			send_player_info.rpc(i)


## 移除玩家
@rpc("any_peer", "call_local")
func remove_player(id: int) -> void:
	if id in player_peer_ids: player_peer_ids.erase(id)
	for p: Player in get_tree().get_nodes_in_group("player"):
		if p.name == str(id):
			p.queue_free()


## 开始游戏
@rpc("any_peer", "call_local")
func start_game(type: GameType) -> void:
	if type == GameType.SINGLE:
		controller_data = [{"charactor_id": 0, "device": "key_", "peer_id": 1}]
	Game.current_type = type
	Game.set_state(Game.GameState.GAMING, 0)


## 设置游戏状态
@rpc("any_peer", "call_local")
func set_state(state: GameState, load_level: int = -1) -> void:
	if state != current_state:
		ui.set_state(state)
		match state:
			GameState.PAUSE:
				get_tree().paused = not get_tree().paused
			GameState.GAMING:
				get_tree().paused = false
			GameState.GAME_OVER, GameState.HALL:
				main.change_scene(hall_tscn)
			GameState.GAMING_MENU, GameState.GAMING_MENU_SETTING:
				get_tree().paused = true
		current_state = state
	
	if load_level > -1 and load_level != current_level:
		change_level(load_level)


## 切换关卡
func change_level(load_level: int) -> void:
	await TransitionLayer.opening_ceremony_close(1, true).finished
	current_level = load_level
	main.change_scene(level_map[current_level])

	TransitionLayer.opening_ceremony_open(1, true, ["关卡 " + str(current_level + 1), "", 3.0])


